梦入琼楼寒有月,行过石树冻无烟

Spring cloud Eureka

本文将会通过 Eureka 来进行服务中心的治理,并实现出 一个 服务中心集群(Eureka Server ……),以及 服务提供者集群(Service Provider ……) 还有一个 服务提供者消费者(Service Consumer) 。之后通过 服务中心 内的 Eureka 来进行服务治理,让 服务消费者(Service Consumer) 调用 服务提供者(Service Provider) 来提供服务。

我们首先使用 Eureka 来实现出一个 服务中心(Eureka Server) 集群,之后通过 Eureaka 所 提供的服务注册(Service Register) 功能来注册 服务提供者(Service Provider),来实现服务提供者集群。

在此后服务消费者(Service Consumer) 使用 Eureka 所提供的 服务注册功能根据服务提供者(Service Provider) 所注册的名称来调用客户端 Feign 来消费 服务提供者所提供的接口

Eureka 是 Netflix 全家桶内项目,他在毕马威在2019年10月所发布的 《颠覆性公司和商业模式》报告中与阿里巴巴分别排名第三,而 Netflix 排名第六位,百度、腾讯分别排名十一和十二位。

虽然 Netlix 排名不如 Alibaba,但他对 Spring cloud 的贡献要早于 Alibaba,因此Netflix 公司所开源的各种项目所组成微服务的核心也不足为奇。

表现层状态转换(Representational State Transfer,REST)由 Roy Thomas Fielding 于 2000年在博士论文中所提出的WWW软件架构风格,目的是放百年在不同软件或程序在网络中相互传递信息,而 Eureka 则是这些项目内基于 REST 服务,主要包含了 服务注册与服务发现功能

构建

Spring Assistant

这从 IDEA 2018 就停止更新了

通过 Spring Assistant 根据自身环境进行选择,当进入选择版本和依赖时,我们需要选择 Spring Cloud Discover -> Eureka Server

Spring Initializr

或者说我们直接通过 IDEA 自带的 Spring Initializr,之后选择 Spring Cloud Discovery -> Eureka Server。当我们构建完成后,肯对会出现一大堆 maven 项目依赖的问题,因此我们需要在 Setting -> Build, Execution, Deployment -> Build Tools -> Maven 下修改 User settings file 所填写的 settings.xml 文件,并写入下述信息,来设置 Alibaba 镜像:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
<mirrors>
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>

<mirror>
<id>uk</id>
<mirrorOf>central</mirrorOf>
<name>Human Readable Name for this Mirror.</name>
<url>http://uk.maven.org/maven2/</url>
</mirror>

<mirror>
<id>CN</id>
<name>OSChina Central</name>
<url>http://maven.oschina.net/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>

<mirror>
<id>nexus</id>
<name>internal nexus repository</name>
<url>http://repo.maven.apache.org/maven2</url>
<mirrorOf>central</mirrorOf>
</mirror>

</mirrors>
</settings>

服务中心


我们所实现的是 服务中心集群,和普通的单点服务中心不一样的是,我们可以保障在系统崩溃时,可以维持系统的 更高的可用性,所以使用服务中心集群(虽然是服务中心集群,但依然可以通过本文来实现单点服务中心)。

Eureka Server demo

我们可以通过一个标准的 Eureka 模板来进行参考,并通过下述模板来进行修改来实现出我们的 服务中心集群 ,需要注意的是下述code不需要执行(因为你就算执行了实现的也是单点服务中心):

application.properties

src/main/resources/application.properties

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 应用名称
spring.application.name=Discovery Server

# Spring 应用端口
server.port=8000

# 节点名称
eureka.instance.hostname=eureka-server.com

# 是否注册到 Eureka Server (默认 true)
eureka.client.register-with-eureka=false

# 是否注册到 Eureka Server 获取注册信息 (默认 true)
eureka.client.fetch-registry=false

# 设置 Eureka Server 交互地址,查询服务和注册服务进行使用(多个以 “,” 分割)
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/

DemoApplication

src/main/java/com/example/demo/DemoApplication.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@EnableEurekaServer
@SpringBootApplication
public class DemoApplication {

public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}

}

hosts

为了让效果更加的接近真实环境下多台服务器内应用协同服务,所以我们可以通过添加几个 虚拟地址(DNS) 来创建一个只有本地可以访问的 URL,来进行演示。

在 Windows 环境下,我们需要修改 C:\Windows\System32\drivers\etc\hosts 文件,并添加:

1
127.0.0.1      abc.com

而本文作者使用的是 debian 环境,即 Linux 系统下则需要简单的修改 /etc/hosts 文件即可,并添加:

1
2
3
4
127.0.0.1	eureka-server.com
127.0.0.1 eureka-server-1.com
127.0.0.1 eureka-server-2.com
127.0.0.1 eureka-server-3.com

为了验证其是否生效,可以直接通过 ping xxx.com 进行查看。

Jar Run

之后我们分别在 eureka-server-1、eureka-server-2、eureka-server-3 项目下按照流程点击 maven 侧栏下的 clean、package等命令,以此来代替 mvn 执行 mvn clean | mvn package命令。

当的包项目为 jar 后,分别进入 eureka-server-1、2、3 内该 jar 包所在位置,并指定根据之前所在 hosts 文件下设置的DNS名称运行项目(有多少服务集群搞多少个):

1
java -jar demo-0.0.1-SNAPSHOT.jar --spring.profiles.active=eureka-server.com

之后进入到http://eureka-server.com:8000/ 即可访问 Eureka 所提供的信息面板中。

eureka-server-1

如果你理解上述的 Eureka Server demo 的配置并结合下述 eureka-server-1~3 所部署的服务中心集群在 Eureka 控制面板和上图基本相似。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 应用名称
spring.application.name=server-clustered

# Spring 应用端口
server.port=8001

# 节点名称
eureka.instance.hostname=eureka-server-1.com

# 是否注册到 Eureka Server (默认 true)
eureka.client.register-with-eureka=true

# 是否注册到 Eureka Server 获取注册信息 (默认 true)
eureka.client.fetch-registry=true

# 设置 Eureka Server 交互地址,查询服务和注册服务进行使用(多个以 “,” 分割)
eureka.client.serviceUrl.defaultZone=http://eureka-server-2.com:8002/eureka/,http://eureka-server-3.com:8003/eureka/

eureka-server-2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 应用名称
spring.application.name=server-clustered

# Spring 应用端口
server.port=8002

# 节点名称
eureka.instance.hostname=eureka-server-2.com

# 是否注册到 Eureka Server (默认 true)
eureka.client.register-with-eureka=true

# 是否注册到 Eureka Server 获取注册信息 (默认 true)
eureka.client.fetch-registry=true

# 设置 Eureka Server 交互地址,查询服务和注册服务进行使用(多个以 “,” 分割)
eureka.client.serviceUrl.defaultZone=http://eureka-server-1.com:8001/eureka/,http://eureka-server-3.com:8003/eureka/

eureka-server-3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 应用名称
spring.application.name=server-clustered

# Spring 应用端口
server.port=8003

# 节点名称
eureka.instance.hostname=eureka-server-3.com

# 是否注册到 Eureka Server (默认 true)
eureka.client.register-with-eureka=true

# 是否注册到 Eureka Server 获取注册信息 (默认 true)
eureka.client.fetch-registry=true

# 设置 Eureka Server 交互地址,查询服务和注册服务进行使用(多个以 “,” 分割)
eureka.client.serviceUrl.defaultZone=http://eureka-server-1.com:8001/eureka/,http://eureka-server-2.com:8002/eureka/

服务提供者


服务提供者(Service provider),我们可以理解为是通过服务中心进行注册,之后为 服务消费者 来提供服务的。我们可以从服务中心,来控制、管理整个微服务的运行、连接状态等。

Eureka Provide demo

DemoApplication

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@SpringBootApplication
@EnableEurekaClient
public class DemoApplication {

public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}

}

我们通过根据之前一样的项目依赖,选择 Eureka Server 即可,进入项目后在启动类中加入 @EnableEurekaClient 注解,来启用其 Eureka 注册和发现功能。

application.properties

1
2
3
4
spring.application.name=server-provide
server.port=8000
provider.name=provider0
eureka.client.serviceUrl.defaultZone=http://eureka-server-3.com:8003/eureka/,http://eureka-server-2.com:8002/eureka/,http://eureka-server-1.com:8001/eureka/

之后我们来设置名称以及控制器需要获取到的信息进行配置,之后通过 eureka.client.serviceUrl.defaultZone来加入服务中心。

HelloController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.example.demo.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {
@Value("${provider.name}")
private String name;

@Value("${server.port}")
private String port;

@RequestMapping("/home")
public String hello() {
String string = "provider:" + name + "port:" + port;
return string;
}
}

控制器的主要用途是来提供接口让 服务消费者 进行获取的,通过application.properties配置文件内相应内容并根据其@Vlue注解以及 @RestController处理HTTP请求,如果你不觉得麻烦可以用下述两个注解代替:

1
2
@Controller
@ResponseBody

Actuator info


Eureka 在其信息面板中 Instances currently registered with Eureka (目前在Eureka 注册的实例)一览中的 Status(状态)下。为开发者提供了一个便捷查询的入口,即 UP (1) - 192.168.43.65:server-provide:8000 => http://192.168.43.65:8000/actuator/info 这是服务提供者的当前在服务中心的链接状态。

当我们点击跳转时,是可以根据其 pom.xml 以及 application.properties 文件内的配置信息单独写入其 JSON 数据的,虽然 Eureka 默认的为 {}

修改添加后结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
{
"app": {
"name": "eureka-cloud-8000"
},
"company": {
"name": "jiangxue.org.cn"
},
"build": {
"application": "server-provide",
"port": "8000"
}
}

我们需要修改其 application.properties 即 Spring 的全局配置文件:

1
2
3
4
5
6
7
8
9
10
spring.application.name=server-provide
server.port=8000
provider.name=localhost

info.app.name=eureka-cloud-8000
info.company.name=jiangxue.org.cn
info.build.application=${spring.application.name}
info.build.port=${server.port}

eureka.client.serviceUrl.defaultZone=http://eureka-server-3.com:8003/eureka/


之后我们还需要修改 pom.xml 配置文件信息,在 <build></build>元素中的 <plugins> 上方,加入 <finalName>信息:

1
2
3
4
5
6
7
<finalName>${project.artifactId}</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>

之后我们可以选择直接在 IDEA 里面运行或通过 jar 包方式运行(虽然是本地环境但还是要整出几十台服务器协同的效果

Jar run


当全部运行完之后,我们将会有三台服务中心集群,以及两台服务提供集群,通过访问我们服务提供集群的控制器即 http://192.168.43.65:8010/hey 都可以正确访问控制器内容时,即可以正常提供服务。

eureka-provide-1

1
2
3
4
5
6
7
8
9
10
spring.application.name=server-provide
server.port=8010
provider.name=localhost

info.app.name=eureka-cloud-${server.port}
info.company.name=jiangxue.org.cn
info.build.application=${spring.application.name}
info.build.port=${server.port}

eureka.client.serviceUrl.defaultZone=http://eureka-server-3.com:8003/eureka/,http://eureka-server-2.com:8002/eureka/,http://eureka-server-1.com:8001/eureka/

eureka-provide-2

1
2
3
4
5
6
7
8
9
10
spring.application.name=server-provide
server.port=8011
provider.name=localhost

info.app.name=eureka-cloud-${server.port}
info.company.name=jiangxue.org.cn
info.build.application=${spring.application.name}
info.build.port=${server.port}

eureka.client.serviceUrl.defaultZone=http://eureka-server-3.com:8003/eureka/,http://eureka-server-2.com:8002/eureka/,http://eureka-server-1.com:8001/eureka/

服务消费者

服务消费者主要通过使用 Feign 来进行实现,Feign 由 Retrofit、JAXRS-2.0 和 WebSocet 所启发,主要用于 Java 到 HTPP 客户端绑定器。因此我们将会通过引入 Feign 依赖来实现服务消费者。

在新建项目时,我们需要注意,需要在 选择依存关系内选择 Spring Web、Eureka Discovery Client。当然之前的服务提供者也可以这样选择,但为了更加方便我们通过选择 Eureka Server 单个依存关系也可以实现。

pom.xml

1
2
3
4
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

添加 spring-cloud-starter-openfeign maven 依赖后可能会报错,此时我们只需要通过点击 Reload ALL Maven Projects 按钮来 重新加载所有 Maven 项目

application.properties

1
2
3
4
spring.application.name=service-consumer
server.port=9000
eureka.client.register-with-eureka=false
eureka.client.serviceUrl.defaultZone=http://eureka-server-3.com:8003/eureka/,http://eureka-server-2.com:8002/eureka/,http://eureka-server-1.com:8001/eureka/

DemoApplication

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class DemoApplication {

public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}

}

通过使用 @EnableDiscoveryClients来启动客户端的服务注册和发现功能,并以 @enableFeignClients 注解来实现远程服务调用。

MyFeignClient interface

1
2
3
4
5
6
7
8
9
10
package com.example.demo;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;

@FeignClient(name = "server-provide")
public interface MyFeignClient {
@RequestMapping(value = "/hey")
public String hello();
}

需要注意的是,我们在此处的方法必须与服务提供者(即服务提供者 Controller)的方法一致

之后我们需要定义一个接口,并使用 @FeignClient 注解来通过 name 值在服务中心进行寻找并连接。在这里我们的服务提供者集群在服务中心所注册的名称是 server-provide

ConsumerController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.example.demo.controller;

import com.example.demo.MyFeignClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ConsumerController {
@Autowired
MyFeignClient myFeignClient;

@RequestMapping("/hey")
public String index() {
return myFeignClient.hello();
}
}

Run


最终我们将服务中心集群、服务提供者集群开起来,以及在 IDEA 中启动服务消费者。之后通过访问 http://localhost:9000/hey 刷新两次看看。

如果端口值从 8010~8011 之间不断调换。那么我们通过 Eureka 来进行服务治理所实现的微服务架构完成。

⬅️ Go back